#include "notescabinet.h"

NotesCabinet::NotesCabinet(QWidget * parent) : QWidget(parent)
	{
		this->parent = qobject_cast<PicKel*>(parent);
		margin = 10;
		Q_UNUSED(margin);

		notesArea = new NotesArea(this);

		notesList = new NoteBooks(this);

		splitter = new QSplitter(this);
		splitter->addWidget(notesList);
		splitter->addWidget(notesArea);
		splitter->setChildrenCollapsible(true);

		layout = new QVBoxLayout(this);
		setLayout(layout);
		layout->addWidget(splitter);

		updateGUI();

		connect(this, SIGNAL(itemDoubleClicked(QListWidgetItem*)), notesArea->view(), SIGNAL(itemDoubleClicked(QListWidgetItem*)));
		connect(notesArea->view(), SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(updateNoteActions()));

		connect(notesList, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(fillNotes(QTreeWidgetItem*,int)));
		connect(notesArea->view(), SIGNAL(itemSelectionChanged()), this, SLOT(updateNoteActions()));
		connect(notesArea->area(), SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateCloseNoteAction(QMdiSubWindow*)));

		connect(this->parent->notesAction(CloseNote), SIGNAL(triggered()), this, SLOT(closeNote()));
		connect(this->parent->notesAction(DeleteNote), SIGNAL(triggered()), this, SLOT(deleteNote()));
		connect(this->parent->notesAction(NewNote), SIGNAL(triggered()), this, SLOT(newNote()));
		connect(this->parent->notesAction(NewNoteBook), SIGNAL(triggered()), this, SLOT(newNoteBook()));
		connect(this->parent->notesAction(RenameNote), SIGNAL(triggered()), this, SLOT(renameNote()));
	}

NotesCabinet::~NotesCabinet(){}

void NotesCabinet::closeNote()
	{
		QMdiSubWindow *sub = notesArea->area()->currentSubWindow();
		if (sub)
			sub->close();
		updateNoteActions();
	}

void NotesCabinet::deleteNote()
	{
		if (notesArea->view()->selectedItems().count() > 0)
		{
			QListWidgetItem *item = notesArea->view()->selectedItems().at(0);
			QMessageBox::StandardButton choice = QMessageBox::question(this, tr("Delete Note"), tr("Are you sure you want to delete \"")+item->text()+"\"?", QMessageBox::Yes | QMessageBox::No);
			if (choice == QMessageBox::Yes)
			{
				if (QFile::remove(item->data(Qt::UserRole).toString()))
				{
					foreach (QMdiSubWindow *sub, notesArea->area()->subWindowList())
					{
						if (sub->windowFilePath() == item->data(Qt::UserRole).toString())
							sub->close();
					}
					delete item;
				}
			}
			updateNoteActions();
		}
	}

void NotesCabinet::fillNotes(QTreeWidgetItem *item, int col)
	{
		Q_UNUSED(col);
		parent->notesAction(NewNote)->setEnabled(true);
		parent->notesAction(NewNoteBook)->setEnabled(true);
		notesArea->view()->clear();
		QDir notesDir(item->text(1),
					  "*.html",
					  QDir::Name | QDir::IgnoreCase,
					  QDir::NoDotAndDotDot | QDir::Files
				);
		foreach (QString entry, notesDir.entryList())
		{
			QString fullPath = QDir::toNativeSeparators(notesDir.cleanPath(notesDir.absoluteFilePath(entry)));
			QFile file(fullPath);
			QListWidgetItem *listItem = new QListWidgetItem(QIcon(":/icons/scaleable-note.png"),
															getTitle(file),
															notesArea->view());
			listItem->setData(Qt::UserRole, fullPath);
		}
	}

QString NotesCabinet::getTitle(QFile &file) const
	{
		QString title;
		if (file.exists())
		{
			QDomDocument html;
			QFileInfo info(file);
			file.open(QIODevice::ReadOnly);
			if (html.setContent(file.readAll()))
			{
				QDomNodeList list = html.elementsByTagName("title");
				if (list.count() > 0)
				{
					if (list.at(0).isElement())
						title = list.at(0).toElement().text();

					if (title.isEmpty())
						title = info.baseName();
				}

				else title = info.baseName();
			}
			file.close();
		}

		return title;
	}

void NotesCabinet::newNote()
	{
		if (notesList->selectedItems().count() > 0)
		{
			bool ok;
			QString noteName = QInputDialog::getText(this, tr("New Note"),
													 tr("Enter a name for the note:"),
													 QLineEdit::Normal, "", &ok);
			if (ok && !noteName.isEmpty())
			{
				QTreeWidgetItem *selectedItem = notesList->selectedItems().at(0);
				QString fileName = noteName;
				fileName.remove(QRegExp("[\\/:*\?\"<>|]")).append(".html");
				fileName.prepend(selectedItem->text(1)+"/");
				QFile noteFile(fileName);
				if (!noteFile.exists())
				{
					if (noteFile.open(QFile::WriteOnly))
					{
						noteFile.close();
						QListWidgetItem *noteItem = new QListWidgetItem(QIcon(":/icons/scaleable-note.png"), noteName, notesArea->view());
						QFileInfo fileInfo(noteFile);
						noteItem->setData(Qt::UserRole, QDir::cleanPath(fileInfo.absoluteFilePath()));
						emit itemDoubleClicked(noteItem);
					}

					else QMessageBox::critical(this, tr("New Note"),
											   tr("Unable to create new note.\n\nConsider checking your permissions."));
				}

				else
				{
					QMessageBox::warning(this, tr("New Note"), tr("Note already exists. Enter a different name."));
					newNote();
				}
			}

			else if (ok && noteName.isEmpty())
			{
				QMessageBox::warning(this, tr("New Note"), tr("Note name is required."));
				newNote();
			}
		}
	}

void NotesCabinet::newNoteBook()
	{
		if (notesList->selectedItems().count() > 0)
		{
			QTreeWidgetItem *item = notesList->selectedItems().at(0);
			QDir dir(item->text(1));
			if (dir.exists())
			{
				bool ok;
				QString dirName = QInputDialog::getText(this, tr("New Notebook"),
														tr("Enter a notebook name:"),
														QLineEdit::Normal, "", &ok);
				if (ok && !dirName.isEmpty())
				{
					dirName.remove(QRegExp("[\\/:*\?\"<>|]"));
					if (dir.mkdir(dirName))
					{
						dir.cd(dirName);
						QStringList texts;
						texts << dirName << dir.absolutePath();
						if (item->text(0) == ".")
						{
							QTreeWidgetItem *bookItem = new QTreeWidgetItem(notesList, texts);
							bookItem->setIcon(0, QIcon(":/icons/book2.png"));
						}

						else
						{
							QTreeWidgetItem *bookItem = new QTreeWidgetItem(item, texts);
							bookItem->setIcon(0, QIcon(":/icons/book2.png"));
						}
					}
				}

				else if (ok && dirName.isEmpty())
				{
					QMessageBox::information(this, tr("New Notebook"), tr("Notebook name is required."));
					newNoteBook();
				}
			}
		}
	}

NoteBooks *NotesCabinet::noteBooks()
	{
		return notesList;
	}

void NotesCabinet::renameNote()
	{
		if (notesArea->view()->selectedItems().count() > 0 && notesList->selectedItems().count() > 0)
		{
			QListWidgetItem *item = notesArea->view()->selectedItems().at(0);
			foreach (QMdiSubWindow *sub, notesArea->area()->subWindowList())
			{
				if (sub->windowFilePath() == item->data(Qt::UserRole).toString())
				{
					QMessageBox::information(this, tr("Rename Note"), tr("Please close the note before renaming."));
					return;
				}
			}

			QTreeWidgetItem *rootItem = notesList->selectedItems().at(0);
			// Change current working directory to work with file names more conveniently.
			if (!QDir::setCurrent(rootItem->text(1)))
				return;

			bool ok;
			QString newName = QInputDialog::getText(this, tr("Rename Note"),
													tr("Enter a new name:"),
													QLineEdit::Normal, item->text(), &ok);
			if (ok && !newName.isEmpty() && item->text() != newName)
			{
				QFile noteFile(item->data(Qt::UserRole).toString(), this);
				QFile newNoteName(item->data(Qt::UserRole).toString(), this);
				newNoteName.setFileName(newName+".html");
				newNoteName.setFileName(newNoteName.fileName().remove(".html").remove(QRegExp("[\\/:*\?\"<>|]"))+".html");
				if (!newNoteName.exists())
				{
					if (noteFile.rename(newNoteName.fileName()))
					{
						item->setText(newName);
						noteFile.setFileName(newNoteName.fileName());
						QFileInfo noteInfo(noteFile);
						item->setData(Qt::UserRole, noteInfo.absoluteFilePath());
						QDomDocument doc;
						noteFile.open(QFile::ReadOnly);
						doc.setContent(noteFile.readAll());
						noteFile.close(); // close to avoid garbage HTML
						QDomNode header = doc.elementsByTagName("head").at(0);
						if (!header.isNull())
						{
							QDomElement headerElem = header.toElement();
							QDomNodeList titles = headerElem.elementsByTagName("title");
							for (int i = 0; i < titles.count(); i++)
								header.removeChild(titles.at(i));
							QDomElement title = doc.createElement("title");
							header.appendChild(title);
						}
						noteFile.open(QFile::WriteOnly);
						// Until i can figure out how to edit the text of an element,
						// i have to use the replace method to apply the new name;
						// an unfortunate work around.
						noteFile.write(doc.toString().replace("<title/>", "<title>"+newName+"</title>").toUtf8());
						noteFile.close();
					}
				}

				else QMessageBox::warning(this, tr("Rename Note"),
										  tr("A note with the same file name already exists.\n\nEnding rename request."));
			}

			else if (ok && !newName.isEmpty() && item->text() == newName)
			{
				QMessageBox::information(this, tr("Rename Note"),
										 tr("You must provide a new name, not the same one."));
				renameNote();
			}

			else if (ok && newName.isEmpty())
			{
				QMessageBox::information(this, tr("Rename Note"), tr("A name is required."));
				renameNote();
			}
		}
	}

void NotesCabinet::updateGUI()
	{
		QSettings settings(QDir::toNativeSeparators(QDir::homePath()+"/.picKel/pickel.cfg"), QSettings::IniFormat, this);

		notesArea->view()->setWrapping(settings.value("NotesDisplay/wrapping", false).toBool());
		notesArea->view()->setUniformItemSizes(settings.value("NotesDisplay/adjustIconSizes", false).toBool());

		if (settings.value("NotesDisplay/listPosition", "top").toString() == "top")
		{
			notesArea->setOrientation(Qt::Vertical);
			notesArea->switchWidgets(Top);
		}

		else if (settings.value("NotesDisplay/listPosition", "top").toString() == "left")
		{
			notesArea->setOrientation(Qt::Horizontal);
			notesArea->switchWidgets(Left);
		}

		else if (settings.value("NotesDisplay/listPosition", "top").toString() == "bottom")
		{
			notesArea->setOrientation(Qt::Vertical);
			notesArea->switchWidgets(Bottom);
		}

		else if (settings.value("NotesDisplay/listPosition", "top").toString() == "right")
		{
			notesArea->setOrientation(Qt::Horizontal);
			notesArea->switchWidgets(Right);
		}

		if (settings.value("NoteEditor/windowViewMode", "tabbed").toString() == "tabbed")
			notesArea->area()->setViewMode(QMdiArea::TabbedView);
		else if (settings.value("NoteEditor/windowViewMode", "tabbed").toString() == "subwindow")
			notesArea->area()->setViewMode(QMdiArea::SubWindowView);
	}

void NotesCabinet::updateCloseNoteAction(QMdiSubWindow *sub)
	{
		parent->notesAction(CloseNote)->setEnabled((bool) sub);
	}

void NotesCabinet::updateNoteActions()
	{
		bool x = (notesArea->view()->selectedItems().count() > 0) ? true : false;
		parent->notesAction(RenameNote)->setEnabled(x);
		parent->notesAction(DeleteNote)->setEnabled(x);
	}
